--- id: TASK-014 title: 'Baseball detail: scoring plays + live situation' status: "\U0001F3C1 Done" assignee: - '@humdrum-tiv' created_date: '2026-06-17 00:23' updated_date: '2026-06-18 01:17' labels: - feature dependencies: [] priority: high ordinal: 14000 --- ## Description MLB detail view: (1) a scoring-plays timeline above the box score, like soccer key events. (2) live situation in the score box — outs, baserunners (bases diamond), current pitcher and current hitter. Situation comes from the already-polled scoreboard endpoint (competitions[].situation: balls/strikes/outs, onFirst/Second/Third, pitcher/batter athlete + summary). Scoring plays come from the summary endpoint plays[] filtered to scoringPlay. ## Acceptance Criteria - [x] #1 model.Game carries a Situation (outs, bases, balls/strikes, pitcher, batter) mapped from scoreboard situation - [x] #2 Detail score box shows outs, bases diamond, current pitcher and hitter for live baseball games - [x] #3 Baseball detail shows a scoring-plays timeline above the box score, team-attributed - [x] #4 Non-baseball sports and non-live games are unaffected ## Implementation Notes Added model.Situation + Game.Situation (mapped from scoreboard competitions[].situation in mapSituation; only when live + pitcher/batter resolved). Added MatchEvent.TeamID; eventSide/eventColor match by id first. summary.go maps plays[] scoringPlay -> Events via mapScoringPlay (▲/▼ inning clock, HR icon 💣, generic run ⚾). detail.go: situationBlock (count/outs pips/bases diamond/pitcher+batter) in score box; eventsBlock parameterized title, baseball renders 'Scoring Plays' above box score. Fixed bigStatus duplicate 'Top 7th Top 7th'. Verified against live PHI-MIA game; offline fixture tests added. ## Final Summary Baseball detail view gains two live features (TASK-014). (1) A situation panel in the score box for live games: balls-strikes count, outs as filled pips, a bases diamond (occupied bases popped goal-orange), and the current pitcher/batter with ESPN stat lines — sourced from model.Game.Situation, mapped from the already-polled scoreboard competitions[].situation (no new fetch). (2) A Scoring Plays timeline above the box score, fed by the summary endpoint's plays[] filtered to scoringPlay, reusing soccer's mirrored eventsBlock (home runs get 💣, other run-scoring plays ⚾). MatchEvent.TeamID added since baseball plays carry only a team id; eventSide/eventColor match by id then name. Also fixed a duplicated live-status string for baseball. Other sports/non-live games unaffected. Offline fixture tests for mapSituation, mapScoringPlay, situationBlock, and section ordering; go vet/build + full suite green.